<?php
class db{
	//变量隐蔽原则：非用户必须知道的，公共的，可以放入类成员中定义处理，如连接句柄和连接
	//用户调用时必然需要用的，少用
	public $host = '';
	public $user = '';
	public $password = '';
	public $database = '';
	public $persist = false;		//是否采用持久连接
	private $conn = NULL;			//连接句柄
	public $result = false;			//结果集合
	public $fields;					//addNew(),edit(),update用于指定字段及数值
	public $check_fields;			// where的条件内字段
	public $tbname;					// addNew()，edit()，update() 操作的表
	public $addNewFlag = false;		// update()调用，设置true后会改为调用Insert()
	public $opened = false; 		//标志已经连接过
	private $count = 0; 			//该脚本的查询次
	
	public function __construct($host="", $user="", $password="", $dbname="", $open=false){
		 ($host != "") && ($this->host = $host);
		 ($user != "") && ($this->user = $user);
		 ($password != "") && ($this->password = $password);
		 ($dbname != "") && ($this->database = $dbname);
		 $open && $this->open();
	}
	public function open($host="", $user="", $password="", $dbname=""){
		if(! $this->opened){
			($host != "") && ($this->host = $host);
			($user != "") && ($this->user = $user);
			($password != "") && ($this->password = $password);
			($dbname != "") && ($this->database = $dbname);
			
			$this->opened = true;
			
			if($this->connect() === false){return false;}
			if($this->select_db() === false){return false;}
		}
		return $this->conn;
	}
	public function set_host($host, $user, $password, $dbname){
		if (is_resource($this->conn)) {
			$this->freeResult($this->result);
			$this->close();
		}
		$this->host = $host;
		$this->user = $user;
		$this->password = $password;
		$this->database = $dbname;
		if ($this->connect()) return true;
		else return false;	
	}
	public function affectedRows(){
		return @mysql_affected_rows( $this->conn);
	}
	public function ping(){
		return is_resource( $this->conn) && @mysql_ping( $this->conn);
	}
	public function close(){
		if( $this->opened){
			$this->opened = false;
			@mysql_close( $this->conn);
		}
	}
	public function connect(){
		if(is_resource($this->conn)){
			return true;
		}
		if ($this->persist){
			( $this->conn = @mysql_pconnect($this->host, $this->user, $this->password) ) or $this->errorlog("mysql_pconnect: $this->host, $this->user");
		}else{
			( $this->conn = @mysql_connect($this->host, $this->user, $this->password, $this->new) ) or $this->errorlog("mysql_connect: $this->host, $this->user");
		}
		if(! is_resource( $this->conn)){
			return false;
		}elseif( mysql_get_server_info() > '4.1'){
			//$this->query("SET SQL_MODE='',CHARACTER_SET_CONNECTION='utf8',CHARACTER_SET_RESULTS='utf8',CHARACTER_SET_CLIENT='binary',NAMES 'utf8'");
			$this->query("SET SQL_MODE='',NAMES 'utf8' ");
		}
		return true;            
	}
	public function select_db( $dbname=""){
		$dbname = $this->database = (($dbname == "") ? $this->database : $dbname);
		return  $dbname=='' ? true : @mysql_select_db($dbname, $this->conn);
	}
	public function error(){
	    return @mysql_error();
	}
	public function errorno(){
	    return @mysql_errno();
	}
	public function query($sql = ''){
		$this->count++;
	    $this->opened or $this->open();  //自动连接
	    //( $this->result = @mysql_query($sql, $this->conn) ) or $this->errorlog( $sql);
	    ( $this->result = @mysql_query($sql, $this->conn) ) or (print  $this->error());
	    return $this->result;
	}
	public function numRows( $result=null){
		is_resource($result) or ($result = $this->result);
	    return @mysql_num_rows($result);
	}
	public function fieldName($field, $result=null){
		is_resource($result) or ($result = $this->result);
		return @mysql_field_name($result,$field);
	}
	//取得auto_increment字段的ID，一般用于
	public function insertID(){
	    return @mysql_insert_id( $this->conn);
	}
	public function data_seek($arg1, $row=0){
		$result = is_resource( $arg1) ? $arg1 : $this->result;
	
		if(!is_resource($arg1) && !is_null($arg1)){
			$row = $arg1;
		}
	
		return @mysql_data_seek($result,$row);
	}
	public function fetchRow($result=null){
		is_resource($result) or ($result = $this->result);
	    return @mysql_fetch_row($result);
	}
	public function fetchObject( $result=null){
		is_resource($result) or ($result = $this->result);
	    return @mysql_fetch_object($result);
	}
	// 常用查询方法
	public function fetchArray($arg1=null, $mode=MYSQL_BOTH){
		$result = is_resource( $arg1) ? $arg1 : $this->result;
		
		if(!is_resource($arg1) && !is_null($arg1))
			$mode = $arg1;
		$array = @mysql_fetch_array($result, $mode);
	    return is_array( $array) ? $array : array();
	}

	public function freeResult( $result=null){
		is_resource($result) or ($result = $this->result);
	    return @mysql_free_result( $result);
	}
	public function addNew( $table_name){
		$this->fields = array();
		$this->addNewFlag = true;
		$this->tbname = $table_name;
	}
	public function edit($table_name){
		$this->fields = array();
		$this->check_fields = array();
		$this->addNewFlag = false;
		$this->tbname = $table_name;
	}
	public function update(){
		//设置字段及数据
		foreach((array)$this->fields as $field_name => $value){
			$qry .= $field_name."='".$value."',";
		}
		//删除上面循环加入的最末尾逗号
		$qry = substr($qry, 0, strlen($qry)-1);
		
		if($this->addNewFlag){
			$qry="INSERT INTO ".$this->tbname." SET " . $qry;
		}else{
			$qry="UPDATE ".$this->tbname." SET ".$qry;
			// 加入where限制，支持最基础的等值，其他条件不支持
			if(count($this->check_fields)>0 && is_array($this->check_fields)){
			   $qry.=" WHERE ";
			   foreach($this->check_fields as $field_name=>$value)
			       $qry.=$field_name."='".$value."' AND ";
			    //去掉上面循环中加入的" AND " 字串
			   $qry=substr($qry,0,strlen($qry)-5);
			}else if(! empty($this->check_fields)){
				//只有一个限制条件时，且条件不限于一个等号，容易有安全问题，使用前必须escape过滤丿丿دد
			   $qry .= " WHERE ".$this->check_fields." ";
			}
		}
		return $this->query($qry);
	}
	public function insert($tbl, $arrData){
		$sql = "INSERT INTO $tbl SET ";
		foreach ((array)$arrData as $key => $value){
			$sql .= "`$key`='$value',";
		}
	
		$this->query(substr($sql,0,-1));
		return $this->insertID();
	}
	public function getAll($sql, $mode=MYSQL_BOTH){
		$result = $this->query( $sql);
		while ($array = $this->fetchArray($result,$mode)) {
			$temp[] = $array;        		
		}
		return (array)$temp;
	}
	public function getOne($sql, $mode=MYSQL_BOTH){
		$result = $this->query( $sql);
		return $this->fetchArray($result,$mode);
	}
	
	//代替普通的SELECT
	public function fromOneTable($tbl, $where=1, $item=array('*'), $multi=0, $mode=MYSQL_BOTH){
		$query = "SELECT ";
		foreach ((array)$item as $key => $value){
			$query .= $value . ',';
		}
		$query = substr($query, 0, -1) . " FROM $tbl WHERE $where" . ($multi ? '' : ' Limit 1');
		return $multi ? $this->getAll($query, $mode) : $this->getOne($query, $mode);
	}
	
	/**
	 * 安全性检浿.调用escape存入后，一定要调unescape取出
	 */
	public function escape( $UserInput){	
		if (is_array($UserInput)) {
			foreach ($UserInput as $k => $v)
				$k = mysql_real_escape_string(trim((string)$v));
			return array($UserInput);
		}
		else 
			return mysql_escape_string( trim( (string)$UserInput));
		
	}
	
	// 递归实现，其实循环会更好
	public function unescape( $PreOutput){
		$PreOutput = is_array($PreOutput) ?
						array_map('unescape', $PreOutput ) :
						stripslashes($PreOutput);
		return $PreOutput;
	}
	
	private function errorlog( $msg='' ){
		$error = date('Y-m-d H:i:s') . ":\n:" . $this->errorno() . $this->error() . $msg . ";\n";		
		oo::logs()->debug($error, 'mysql.txt');
		die('Sorry,Page Invalid!!!');
	}
	public function __destruct(){
		$this->close();
	}
	
	public function test() {
		 ($_GET or $_POST) ? $RetChar ="<br></br>" : $RetChar = "\r\n";
		 
		echo "==================== connect() =======================" . $RetChar;
		self::open('127.0.0.1','ticket','ticket','test');
		if ($this->ping())
			echo "connect() and ping() success". $RetChar;
		echo "==================== query(),fetchArray() =======================" . $RetChar;
		self::query('create table IF NOT EXISTS ‘test_abc‘ (id int, name varchar(64), sex int)');
		$test_data = array('id' =>1, 'name' =>'Chair','sex' =>1);
		self::insert('test_abc', $test_data);
			
		self::query('select * from test_abc limit 3');
		echo "Return row number is : " . self::numRows($this->result) . $RetChar;
		while ($arr = self::fetchArray($this->result, MYSQL_ASSOC))
			foreach ($arr as $k => $v)
				echo  $k . " => " . $v . $RetChar;
				
		echo "==================== GetAll() =======================" . $RetChar;
		$arr_row = self::getAll('select * from test_abc');
		foreach ($arr_row as $k => $v)
			foreach ($v as $kk => $vv)
				echo $kk . " => " . $vv . $RetChar;
		
		echo "==================== insert() =======================" . $RetChar;
		
		echo "==================== update() =======================" . $RetChar;
		
		
	}
	
}
	//MainTest() 类测试用，可作为单元测试用途
	$TestDb = new db('127.0.0.1','ticket','ticket','test');
	$TestDb->test();